package com.h2.gwt.util.appstorage;

import java.util.Set;
import java.util.TreeSet;

/**
 * Default implementation of {@link IParameterNameStrategy}, which
 * supports case-insensitive matching of parameters and supports matching
 * with/without "_" parameters.
 */
public class DParameterNameStrategy implements IParameterNameStrategy {
   
   private boolean _ignoreCase = true;
   
   private boolean _allowNonUnderScore = true;
   
   ////
   ////
   
   public String getFriendlyName(String name) {
      if (name == null || name.length() <= 0) {
         return name;
      }
      if (name.charAt(0) == '_') {
         name = name.substring(1);
      }
      return name.replaceAll("([a-z])([A-Z])", "$1_$2").toLowerCase();
   }
   
   public String findMatch(String name, Set<String> available,
         boolean nullOnMismatch) {
      
      // exact matches
      Set<String> possibles = getNames(name);
      for (String possible: possibles) {
         if (available.contains(possible)) {
            return possible;
         }
      }
      
      if (isIgnoreCase()) {
         for (String aname: available) {
            for (String pname: possibles) {
               if (aname.equalsIgnoreCase(pname)) {
                  return aname;
               }
            }
         }
      }
      /*
       * In some cases if we do not find a match in available set, this
       * method is expected to return name as is. In some cases we need 
       * to return null. Hence this boolean check.
       */
      if (nullOnMismatch) {
         return null;
      }
      return name;
   }
   
   protected Set<String> getNames(String name) {
      Set<String> names = new TreeSet<String>();
      names.add(name);
      names.add(name.replace("_", ""));
      
      if (isAllowNonUnderScore()) {
         if (name.indexOf("_") == -1) {
            StringBuilder builder = new StringBuilder(String.valueOf(name.charAt(0)));
            for (int i = 1; i < name.length(); i++) {
               char c = name.charAt(i);
               if (Character.isUpperCase(c)) {
                  builder.append("_").append(c);
               }
               else {
                  builder.append(c);
               }
            }
            names.add(builder.toString());
         }
      }
      
      return names;
   }
   
   public void setIgnoreCase(boolean ignoreCase) {
      this._ignoreCase = ignoreCase;
   }
   
   public boolean isIgnoreCase() {
      return _ignoreCase;
   }
   
   public void setAllowNonUnderScore(boolean allowNonUnderScore) {
      this._allowNonUnderScore = allowNonUnderScore;
   }
   
   public boolean isAllowNonUnderScore() {
      return _allowNonUnderScore;
   }
}
